package com.one.intercept;

import com.alibaba.fastjson.JSON;
import com.one.annotation.RequestPermission;
import com.one.constant.RedisPrefixConstant;
import com.one.constant.RequestReturnConstant;
import com.one.util.RedisUtils;
import com.one.util.RequestReturnFactory;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * @Author ShiWen
 * @date 2022/1/14 10:50
 * @Version 1.0
 * @Description TODO 请求权限许可拦截器
 */
@Slf4j
public class RequestPermissionInterceptor implements HandlerInterceptor {
    @Autowired
    private RedisUtils redisUtils;
    @Override
    public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object handler) throws Exception {
        // 判断是否需要进行请求权限许可校验（关注目标请求方法上有没有请求许可注解@RequestPermission）
        if (this.checkTargetMethodAddRequestPermission(handler)){
            // 从redis中获取token对应的用户信息
            String userToken = httpServletRequest.getHeader("token");
            //判断token是否为空
            httpServletResponse.setCharacterEncoding("UTF-8");
            httpServletResponse.setContentType("application/json; charset=utf-8");
            if (StringUtils.isEmpty(RedisPrefixConstant.LOGIN_TOKEN+userToken)){
                log.warn("**** token参数为空，权限不足，请重新登录！****");
                //拦截请求
                httpServletResponse.getWriter().write(JSON.toJSONString(RequestReturnFactory.fail(
                        RequestReturnConstant.USER_NO_LOGIN_CODE,RequestReturnConstant.USER_NO_LOGIN__MSG
                )));
                return false;
            }
            // 判断token是否有效
            Object userObj = redisUtils.get(RedisPrefixConstant.LOGIN_TOKEN+userToken);
            if (ObjectUtils.isEmpty(userObj)){
                log.warn("**** token失效或者非法，权限不足，请重新登录！****");
                //拦截请求
                httpServletResponse.getWriter().write(JSON.toJSONString(RequestReturnFactory.fail(
                        RequestReturnConstant.USER_NO_LOGIN_CODE,RequestReturnConstant.USER_NO_LOGIN__MSG
                )));
                return false;
            }
        }
        // 请求放行
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {

    }

    @Override
    public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {

    }
    /**
     * @author ShiWen
     * @date 2022/1/5 10:54
     * @param
     * @return
     * @description 判断目标请求处理方法是否添加了请求权限许可注解
     */
    private boolean checkTargetMethodAddRequestPermission(Object handler){
        // 判断当前handler对象是否是能映射到目标请求处理方法
        if (handler instanceof HandlerMethod){
            // 强转为目标请求处理方法对象 （封装了目标请求处理方法的所有内容）
            HandlerMethod handlerMethod = (HandlerMethod) handler;
            // 获取目标请求方法
            RequestPermission requestPermission = handlerMethod.getMethod().getAnnotation(RequestPermission.class);
            // 判断此注解是否存在，如果不存在，不一定不需要校验，再判断注解是否再类上
            if (null == requestPermission){
                // 从目标请求处理类上再次获取此注解
                requestPermission = handlerMethod.getMethod().getDeclaringClass().getAnnotation(RequestPermission.class);
            }
            // 判断请求权限许可注解是否存在，
            return null!=requestPermission;
        }
        // 不需要进行权限校验，直接放行
        return false;
    }
}
